package com.xwj;

import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.reflect.Field;

/**
 * @author xwj
 * @date 2020/10/16
 */
public class JavaVMStackSOF {
    private int stackLength = 1;
    public void stackLeak() {
        stackLength++;
        stackLeak();
    }

    public static boolean isRun = true;

    public static void main(String[] args) throws Throwable {
//        JavaVMStackSOF oom = new JavaVMStackSOF();
//        try {
//            oom.stackLeak();
//        } catch (Throwable e) {
//            System.out.println("stack length:" + oom.stackLength);
//            throw e;
//        }

        String abc = new String("abc");
        System.out.println(abc.getClass() + "@" + abc.hashCode());
        final ReferenceQueue<String> referenceQueue = new ReferenceQueue<String>();
        new Thread() {
            @Override
            public void run() {
                while (isRun) {
                    Object obj = referenceQueue.poll();
                    if (obj != null) {
                        try {
                            Field rereferent = Reference.class
                                    .getDeclaredField("referent");
                            rereferent.setAccessible(true);
                            Object result = rereferent.get(obj);
                            System.out.println("gc will collect："
                                    + result.getClass() + "@"
                                    + result.hashCode() + "\t"
                                    + (String) result);
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }.start();

        PhantomReference<String> abcWeakRef = new PhantomReference<String>(abc, referenceQueue);

        abc = null;
        System.gc();
        Thread.sleep(3000);
        isRun = false;
    }
}
